﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace Common
{
    /// <summary>
    /// 类型工具类
    /// </summary>
    public class ClassTypeUtils
    {
         /// <summary>  
        /// 根据指定的类全名返回对象实例  
        /// </summary>  
        /// <param name="objFullName">对象完整名称（包名和类名），如：com.xxx.Test</param>  
        public static T Instance<T>(string FullClassTypeName, params object[] args) where T : class
        {
            return Instance(FullClassTypeName,args) as T;
        }

        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="FullClassTypeName"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object Instance(string FullClassTypeName, params object[] args)
        {
            var type = FindType(FullClassTypeName);
            object obj = Instance(type,args);
            return obj;
        }

        /// <summary>
        /// 实例化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static T Instance<T>(Type type, params object[] args) where T : class
        {
            var ret = Instance(type,args)as T;
            return ret;
        }

        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="type"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object Instance(Type type, params object[] args)
        {
            object ret = null;
            if (args == null || args.Length == 0) ret = Activator.CreateInstance(type, true);
            else ret = Activator.CreateInstance(type, args);
            return ret;
        }

        private static Dictionary<string, Type> getTypeCache = new Dictionary<string, Type>();

        /// <summary>  
        /// 查询指定类
        /// </summary>  
        /// <param name="FullClassTypeName">对象完整名称（包名和类名），如：com.xxx.Test或 com.xxx.Test,com.xxx</param>  
        public static Type FindType(string FullClassTypeName)
        {
            if (string.IsNullOrWhiteSpace(FullClassTypeName)) throw new Exception("FullClassTypeName con not empty");
            Type type = null;
            if (getTypeCache.TryGetValue(FullClassTypeName, out type) == false)
            {
                string typeName = FullClassTypeName;
                string assemblyName = null;
                var names = typeName.Split(',');
                if (names.Length > 1)
                {
                    typeName = names[0];
                    assemblyName = names[1];
                }
                type = Type.GetType(typeName);
                if (type == null)
                {
                    Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
                    foreach (Assembly a in ass)
                    {
                        if (assemblyName == null || a.FullName.StartsWith(assemblyName))
                        {
                            type = a.GetType(typeName, false, false);
                            if (type != null) break;
                        }
                    }
                }
                getTypeCache[FullClassTypeName] = type;
            }
            return type;
        }
 
        /// <summary>
        /// 查找子类
        /// </summary>
        public static IList<Type> FindImplementedTypes(string BaseFullClassTypeName)
        {
            return FindImplementedTypes(BaseFullClassTypeName, null);
        }

        /// <summary>
        /// 查找子类
        /// </summary>
        public static IList<Type> FindImplementedTypes(string BaseFullClassTypeName, string FindNameSpace)
        {
            var baseType = FindType(BaseFullClassTypeName);
            return FindImplementedTypes(baseType, FindNameSpace);
        }

        /// <summary>
        /// 查找子类
        /// </summary>
        public static IList<Type> FindImplementedTypes(Type BaseType)
        {
            return FindImplementedTypes(BaseType, null);
        }

        private static Dictionary<string, IList<Type>> findTypeCache = new Dictionary<string, IList<Type>>();
        /// <summary>
        /// 查找子类
        /// </summary>
        /// <param name="BaseFullClassTypeName"></param>
        /// <param name="FindNameSpace"></param>
        /// <returns></returns>
        public static IList<Type> FindImplementedTypes(Type BaseType, string FindNameSpace)
        {
            IList<Type> types = null;
            var cacheKey = BaseType.Name + ">" + FindNameSpace;
            if (findTypeCache.TryGetValue(cacheKey, out types) == false)
            {
                types = new List<Type>();
                Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
                foreach (Assembly a in ass)
                {
                    try
                    {
                        foreach (var t in a.GetTypes())
                        {
                            if (FindNameSpace == null || (t.Namespace != null && t.Namespace.StartsWith(FindNameSpace)))
                            {
                                if (
                                    t.IsSubclassOf(BaseType)
                                    || (BaseType.IsInterface && t.GetInterface(BaseType.FullName) != null)
                                    || (t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == BaseType)
                                    )
                                {
                                    types.Add(t);
                                }
                            }
                        }
                    }
                    catch { }
                }
                findTypeCache[cacheKey] = types;
            }
            return types;
        }
    }
}
